package com.review.analysis;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.review.model.SarifModels;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class StaticAnalysisService {

	private final ObjectMapper mapper = new ObjectMapper();

	public SarifModels.SarifRun runSemgrep(File repoRoot) throws Exception {
		List<String> cmd = new ArrayList<>();
		cmd.add("semgrep");
		cmd.add("--config");
		cmd.add("auto");
		cmd.add("--json");
		ProcessBuilder pb = new ProcessBuilder(cmd);
		pb.directory(repoRoot);
		pb.redirectErrorStream(true);
		Process p = pb.start();
		StringBuilder out = new StringBuilder();
		try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
			String line;
			while ((line = br.readLine()) != null) out.append(line);
		}
		int code = p.waitFor();
		if (code != 0 && code != 1) {
			throw new RuntimeException("semgrep exited with code " + code);
		}
		return parseSemgrepJson(out.toString());
	}

	private SarifModels.SarifRun parseSemgrepJson(String json) throws Exception {
		SarifModels.SarifRun run = new SarifModels.SarifRun();
		JsonNode root = mapper.readTree(json);
		JsonNode results = root.get("results");
		if (results == null || !results.isArray()) return run;
		for (JsonNode r : results) {
			SarifModels.SarifResult s = new SarifModels.SarifResult();
			s.ruleId = r.path("check_id").asText();
			s.level = mapSeverity(r.path("extra").path("severity").asText());
			s.message = r.path("extra").path("message").asText();
			JsonNode loc = r.path("path");
			s.file = loc.asText();
			s.line = r.path("start").path("line").asInt();
			run.results.add(s);
		}
		return run;
	}

	private String mapSeverity(String sev) {
		return switch (sev == null ? "" : sev.toLowerCase()) {
			case "error", "high" -> "error";
			case "warning", "medium" -> "warning";
			default -> "note";
		};
	}
}

